﻿/*
   Open Intel 
   Copyright © 2011 – ISC. All Rights Reserved.
*/

using System;
using ISC.MapDotNetServer.Common.Data;
using ISC.MapDotNetServer.Common.Maps.Extended;
using ISC.RIM.Silverlight;

namespace OI.Framework
{
    public class DensityMapRenderer : ITileRenderer
    {
        #region DATA
        private const int SampleRadius = 9;
        private const double SampleStdDevRadius = 4.0;
        private const int CellSize = 64;
        private const double OverfetchMargin = 1.33;

        // are we tracking count or sum
        public enum AccumTypes
        {
            Count,
            Sum
        }
        public AccumTypes AccumType { get; set; }

        // index of the column to track
        public int ColumnIdx { get; set; }

        // for dynamically tracking grid limits
        public double MaxValue { get; set; }
        public static object MaxValueLock = new object();
        #endregion


        #region INTERFACE METHODS
        public bool CanRenderInBackground()
        {
            return true;
        }

        
        public System.Collections.Generic.List<ITileRenderInfo> ClassificationPreRender(QuadTile quadTile, QueryResultTable resultsTable, ITileProjection proj)
        {
            return null;
        }


        public object Render(QuadTile quadTile, QueryResultTable resultsTable, ITileProjection proj)
        {
            try
            {
                double tileMaxValue = 0.0;

                // new density mapping renderer
                var renderer = new DMRender();

                // row processor is used to filter and track max
                var filterRow = new Func<QueryResultRow, double>(row =>
                {
                    double val = 1.0;
                    if (AccumType == AccumTypes.Sum)
                    {
                        val = Convert.ToDouble(row.Values[ColumnIdx]);
                    }

                    // update watermark
                    tileMaxValue += val;
                    lock (MaxValueLock)
                    {
                        if (tileMaxValue > MaxValue)
                        {
                            MaxValue = tileMaxValue;
                        }
                    }

                    return val;
                });


                return renderer.Render(
                    quadTile.Dispatcher,
                    resultsTable,
                    quadTile.BoundsMap,
                    OverfetchMargin,
                    filterRow,
                    null,
                    null,
                    CellSize,
                    SampleRadius,
                    SampleStdDevRadius,
                    0,                                              
                    MaxValue / (CellSize / SampleStdDevRadius),                                       
                    false,
                    true);
            }
            catch (Exception ex)
            {
                return ex;
            }
        }

        #endregion
    }
}
